package demo.service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.auth.core.spi.AbstractAuthenticationHandler;
import org.apache.sling.auth.core.spi.AuthenticationInfo;

@Service
@Component(immediate = true)
@Properties(value = { @Property(name = "path", value = "/"),
		@Property(name = "service.ranking", value = "999"),
		@Property(name = "authtype", value = "ajaxauth") })
public class AjaxAuthenticationHandler extends AbstractAuthenticationHandler {

	Map<String, AuthenticationInfo> loginMap = new HashMap<String, AuthenticationInfo>();

	public void dropCredentials(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String loginId = getLoginId(request);

		if (loginMap.containsKey(loginId)) {
			loginMap.remove(loginId);
		}

	}

	private String getLoginId(HttpServletRequest request) {
		String result = request.getSession(true).getId();

		return result;
	}

	private boolean isLoggedIn(HttpServletRequest request) {
		return loginMap.containsKey(getLoginId(request));
	}

	public AuthenticationInfo extractCredentials(HttpServletRequest request,
			HttpServletResponse response) {

		String username = request.getParameter("x_username");
		if (isLoggedIn(request)) {
			return loginMap.get(getLoginId(request));
		}

		String pwd = request.getParameter("x_password");

		AuthenticationInfo authenticationInfo = new AuthenticationInfo(
				"ajaxauth", "anonymous", "anonymous".toCharArray());
		if (pwd != null && username != null) {
			char[] password = pwd.toCharArray();
			authenticationInfo = new AuthenticationInfo("ajaxauth", username,
					password);
		}

		return authenticationInfo;
	}

	@Override
	public void authenticationFailed(HttpServletRequest request,
			HttpServletResponse response, AuthenticationInfo authInfo) {
		response.setStatus(200);
		try {
			response.getWriter().println("{success: false}");
			response.flushBuffer();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public boolean authenticationSucceeded(HttpServletRequest request,
			HttpServletResponse response, AuthenticationInfo authInfo) {
		response.setStatus(200);
		String user = authInfo.getUser();
		if (isLoggedIn(request) || "anonymous".equals(user))
			return false;

		final StringBuilder header = new StringBuilder();

		String loginId = getLoginId(request);

		// default setup with name, value, cookie path and HttpOnly
		header.append("login").append("=").append(loginId);
		header.append("; Path=").append("/");
		header.append("; HttpOnly"); // don't allow JS access

		// ensure the cookie is secured if this is an https request
		if (request.isSecure()) {
			header.append("; Secure");
		}

		response.addHeader("Set-Cookie", header.toString());

		loginMap.put(loginId, authInfo);

		try {
			response.getWriter()
					.println("{success: true, user:'" + user + "'}");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return true;
	}

	public boolean requestCredentials(HttpServletRequest request,
			HttpServletResponse response) throws IOException {

		return true;
	}

}
